package com.caiya.session.web.http;

import java.util.List;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Strategy for reading and writing a cookie value to the {@link HttpServletResponse}.
 *
 * @author Rob Winch
 * @since 1.1
 */
public interface CookieSerializer {

    /**
     * Writes a given {@link CookieValue} to the provided {@link HttpServletResponse}.
     *
     * @param cookieValue the {@link CookieValue} to write to
     *                    {@link CookieValue#getResponse()}. Cannot be null.
     */
    void writeCookieValue(CookieValue cookieValue);

    /**
     * Reads all the matching cookies from the {@link HttpServletRequest}. The result is a
     * List since there can be multiple {@link Cookie} in a single request with a matching
     * name. For example, one Cookie may have a path of / and another of /context, but the
     * path is not transmitted in the request.
     *
     * @param request the {@link HttpServletRequest} to read the cookie from. Cannot be
     *                null.
     * @return the values of all the matching cookies
     */
    List<String> readCookieValues(HttpServletRequest request);

    /**
     * Contains the information necessary to write a value to the
     * {@link HttpServletResponse}.
     *
     * @author Rob Winch
     * @author Vedran Pavic
     * @since 1.1
     */
    class CookieValue {

        private final HttpServletRequest request;

        private final HttpServletResponse response;

        private final String cookieValue;

        private int cookieMaxAge = -1;

        /**
         * Creates a new instance.
         *
         * @param request     the {@link HttpServletRequest} to use. Useful for determining
         *                    the context in which the cookie is set. Cannot be null.
         * @param response    the {@link HttpServletResponse} to use.
         * @param cookieValue the value of the cookie to be written. This value may be
         *                    modified by the {@link CookieSerializer} when writing to the actual cookie so
         *                    long as the original value is returned when the cookie is read.
         */
        public CookieValue(HttpServletRequest request, HttpServletResponse response,
                           String cookieValue) {
            this.request = request;
            this.response = response;
            this.cookieValue = cookieValue;
            if ("".equals(this.cookieValue)) {
                this.cookieMaxAge = 0;
            }
        }

        /**
         * Gets the request to use.
         *
         * @return the request to use. Cannot be null.
         */
        public HttpServletRequest getRequest() {
            return this.request;
        }

        /**
         * Gets the response to write to.
         *
         * @return the response to write to. Cannot be null.
         */
        public HttpServletResponse getResponse() {
            return this.response;
        }

        /**
         * The value to be written. This value may be modified by the
         * {@link CookieSerializer} before written to the cookie. However, the value must
         * be the same as the original when it is read back in.
         *
         * @return the value to be written
         */
        public String getCookieValue() {
            return this.cookieValue;
        }

        /**
         * Get the cookie max age. The default is -1 which signals to delete the cookie
         * when the browser is closed, or 0 if cookie value is empty.
         *
         * @return the cookie max age
         */
        public int getCookieMaxAge() {
            return this.cookieMaxAge;
        }

        /**
         * Set the cookie max age.
         *
         * @param cookieMaxAge the cookie max age
         */
        public void setCookieMaxAge(int cookieMaxAge) {
            this.cookieMaxAge = cookieMaxAge;
        }

    }

}
